//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System.Windows;
using System.Windows.Controls;
using Microsoft.Research.ScientificWorkflow.TridentModel;
using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
using System.ComponentModel;
using Microsoft.Research.ScientificWorkflow.TridentUtilities;
using System;

namespace Microsoft.Research.ScientificWorkflow.UIDesigner
{
    /// <summary>
    /// Interaction logic for LabelDialog.xaml
    /// </summary>
    public partial class LabelDialog : Window, INotifyPropertyChanged
    {
        private UIHelper uiHelper;
        private WorkflowMetadata workflow;
        private string enteredLabel;
        private bool labelNotUnique;
        private string errorMessage;

        /// <summary>
        /// Initializes a new instance of the Label dialog.
        /// </summary>
        /// <param name="workflow"></param>
        /// <param name="uiHelper"></param>
        public LabelDialog(WorkflowMetadata workflow, UIHelper uiHelper)
        {
            this.uiHelper = uiHelper;
            this.workflow = workflow;
            InitializeComponent();
            
            this.LabelWorkflow = new DelegateCommand<object>(p => this.LabelWorkflowExecute(), p => this.LabelWorkflowCanExecute());
            this.CloseWindow = new DelegateCommand<object>(p => this.CloseWindowExecute());
            this.DataContext = this;
            if (!string.IsNullOrEmpty(workflow.VersionLabel))
            {
                this.EnteredLabel = workflow.VersionLabel;
            }
        }

        /// <summary>
        /// Gets a flag which specifies whether the labeling of a workflow is a success.
        /// </summary>
        public bool LabelWorkflowSuccess { get; private set; }

        /// <summary>
        /// Gets a flag to check if the label is valid.
        /// </summary>
        public bool LabelNotValid 
        {
            get
            {
                return this.labelNotUnique;
            }
            private set
            {
                this.labelNotUnique = value;
                this.RaisePropertyChanged("LabelNotValid");
            }
        }

        /// <summary>
        /// Gets the error message to be shown to the user if the label is invalid.
        /// </summary>
        public string ErrorMessage
        {
            get
            {
                return this.errorMessage;
            }
            private set
            {
                this.errorMessage = value;
                this.RaisePropertyChanged("ErrorMessage");
            }
        }

        /// <summary>
        /// Gets the command which labels a workflow.
        /// </summary>
        public DelegateCommand<object> LabelWorkflow { get; private set; }

        /// <summary>
        /// Gets the command which closes the window.
        /// </summary>
        public DelegateCommand<object> CloseWindow { get; private set; }

        /// <summary>
        /// Gets or sets the label entered by the user.
        /// </summary>
        public string EnteredLabel
        {
            get
            {
                return this.enteredLabel;
            }
            set
            {
                this.enteredLabel = value;
                this.LabelWorkflow.RaiseCanExecuteChanged();
            }
        }

        /// <summary>
        /// Create a label for the workflow.
        /// </summary>
        private void LabelWorkflowExecute()
        {
            try
            {
                string trimmedLabel = this.EnteredLabel.Trim();

                // No change in the text field.
                if (!string.IsNullOrEmpty(this.workflow.VersionLabel) && this.workflow.VersionLabel.Equals(trimmedLabel,StringComparison.OrdinalIgnoreCase))
                {
                    this.LabelWorkflowSuccess = true;
                    this.Close();
                }
                // Check if the workflow contains invalid chars.
                else if (!TridentWorkflowModel.CheckNameForInvalidCharacters(trimmedLabel))
                {
                    this.LabelNotValid = true;
                    this.ErrorMessage = TridentResourceManager.GetString("LabelInvalid");
                }
                else
                {
                    //Check if the label entered is unique.
                    if (this.uiHelper.ValidateLabel(this.workflow.ParentCategoryId, trimmedLabel, this.workflow.Name))
                    {
                        this.LabelNotValid = true;
                        this.uiHelper.LabelWorkflow(this.workflow.Id, trimmedLabel);
                        this.workflow.VersionLabel = trimmedLabel;
                        this.LabelWorkflowSuccess = true;
                        this.Close();
                    }
                    else
                    {
                        this.LabelNotValid = true;
                        this.ErrorMessage = TridentResourceManager.GetString("LabelNotUnique");
                    }
                }
            }
            catch
            {
                this.Close();
                throw;
            }
        }

        /// <summary>
        /// Close the window.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args</param>
        private void CloseWindowExecute()
        {
            this.Close();
        }

        /// <summary>
        /// Checks whether the Save label button can be enabled or not.
        /// </summary>
        /// <returns>True if the button can be enabled; false otherwise.</returns>
        private bool LabelWorkflowCanExecute()
        {
            return !string.IsNullOrEmpty(this.enteredLabel);
        }

        /// <summary>
        /// The handler which helps the window to be dragged about using the mouse.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args</param>
        private void Border_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        #endregion

        /// <summary>
        /// Event handler for the loaded event of the textbox. Brings the textbox into focus.
        /// </summary>
        /// <param name="sender">Sender of the event.</param>
        /// <param name="e">The event arguments.</param>
        private void LabelTextbox_Loaded(object sender, RoutedEventArgs e)
        {
            this.LabelTextbox.Focus();
        }

    }
}
